/**
 * @Title: PreFilter.java
 * @Package com.xingyun.s2b2c.gateway.test
 * @Description: TODO(用一句话描述该文件做什么)
 * @author Administrator
 * @date 2018年9月11日 下午3:37:37
 * @version V1.0
 */
package com.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.common.global.R;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.cloud.netflix.zuul.util.ZuulRuntimeException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 错误过滤器 ,在处理请求时发生错误时调用
 */
@Component
@Slf4j
public class ErrorFilter extends ZuulFilter {

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        try {
            RequestContext context = RequestContext.getCurrentContext();
            HttpServletResponse response = context.getResponse();
            if (response == null) {
                return null;
            }
            Throwable exception = context.getThrowable().getCause();
            log.warn(exception.getMessage(), exception);

            String msg = "服务器开小差了,请稍后再试!";
            if (exception instanceof FilterException) {
                msg = exception.getMessage();
            }

            // 删除该异常信息,不然在下一个过滤器中还会被执行处理
            context.remove("throwable");
            // 响应给客户端信息
            response.setHeader("Content-type", "application/json;charset=UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            try (PrintWriter writer = response.getWriter()) {
                writer.print(JSON.toJSONString(R.error(GatewayDefaultEnum.DEFAULT_ERROR.code(), String.format(GatewayDefaultEnum.DEFAULT_ERROR.message(), msg), null)));
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            ReflectionUtils.rethrowRuntimeException(e);
        }
        return null;
    }

    public ZuulException findZuulException(Throwable throwable) {
        if (ZuulRuntimeException.class.isInstance(throwable.getCause())) {
            return (ZuulException) throwable.getCause().getCause();
        } else if (ZuulException.class.isInstance(throwable.getCause())) {
            return (ZuulException) throwable.getCause();
        } else {
            return ZuulException.class.isInstance(throwable) ? (ZuulException) throwable : new ZuulException(throwable, 500, (String) null);
        }
    }

    @Override
    public String filterType() {
        return FilterConstants.ERROR_TYPE;
    }

    @Override
    public int filterOrder() {

        return FilterConstants.SEND_ERROR_FILTER_ORDER - 1;
    }

}
